<?php
declare(strict_types=1);

namespace App\Service;

use App\Model\Dao\SysRoleDao;
use App\Utils\CustomUtils;
use Hyperf\Di\Annotation\Inject;
use App\Model\Dao\SysAdminDao;
use App\Model\Dao\SysAdminMchRelationDao;
use App\Model\Dao\SysAccessDao;
use App\Model\Dao\SysNodeDao;
use App\Service\SysRoleService;
use App\Exception\XZXValidationException;
use App\Constants\XZXResponseCode;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Coroutine;
use App\Utils\DateUtils;
// use Cassandra\Type\Custom;
use App\Utils\OpenService;
// use Cassandra\Custom as CassandraCustom;
use Hyperf\DbConnection\Db;
use App\Utils\ArrayUtils;
use Hyperf\Utils\Arr;
use App\Service\CommonService;
// use Cassandra\Type\Custom;
use Phper666\JWTAuth\JWT;
use Hyperf\Database\Query\Builder;
use App\Utils\Tree;

class SysAdminService
{
    /**
     * @Inject()
     * @var JWT
     */
    private $JWT;

    /**
     * @Inject()
     * @var SysRoleService
     */
    private $SysRoleService;


    /**
     * @Inject()
     * @var CommonService
     */
    private $CommonService;

    /**
     * @Inject()
     * @var SysAdminDao
     */
    private $SysAdminDao;

    /**
     * @Inject()
     * @var SysRoleDao
     */
    private $SysRoleDao;

    /**
     * @Inject()
     * @var SysAccessDao
     */
    private $SysAccessDao;

    /**
     * @Inject()
     * @var SysNodeDao
     */
    private $SysNodeDao;

    /**
     * @Inject()
     * @var SysAdminMchRelationDao
     */
    private $SysAdminMchRelationDao;

    public function get($param)
    {
        $result = $this->SysAdminDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        if(isset($result['createTime'])){
            $result['createTime'] = DateUtils::getDateTime($result['createTime']);
        }
        $relation = $this->SysAdminMchRelationDao->getWhereList(['adminId' => $param['id']]);
        if (!empty($relation)) {
            $result['mchIdList'] = array_column($relation, 'mchId');
        } else {
            $result['mchIdList'] = [];
        }

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$result);
    }

    public function del($param)
    {
        $result = $this->SysAdminDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        
        try {
            $result = $this->SysAdminDao->del($param['id'],false);
        } catch (\Throwable $th) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DEL_FAIL));
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function add($param)
    {

        $role = $this->SysRoleDao->get($param['roleId']);
        if (empty($role)) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        // 销售需要处理
        if ($role['extraType'] == 1 && empty($param['level'])) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::SALES_LEVEL_REQUIRED));
        }
        if ($role['extraType'] == 1 && $param['level'] == 2 && empty($param['parentId'])) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::SALES_PARENT_ID_REQUIRED));
        }

        $salt        = OpenService::getNonceStr(5);
        $newPassword = CustomUtils::genPassWord($param['password'],$salt);

        // 生成GoogleAuth密钥
        $googleAuthSecret = $this->CommonService->generateGoogleAuthSecret();

        $data = $param;
        $data['id'] = CustomUtils::createUUID();
        $data['createTime'] = time();
        $data['salt'] = $salt;
        $data['password'] = $newPassword;
        $data['googleAuthSecret'] = $googleAuthSecret;
        $data['nick'] = $param['username'];
        $data['level'] = isset($param['level']) ? $param['level'] : 0;
        $data['parentId'] = isset($param['parentId']) ? $param['parentId'] : '';
        unset($data['mchIdList']);
        unset($data['uid']);
        unset($data["password_confirmation"]);
        CustomUtils::xzxDebug($data);
       
        Db::beginTransaction();
        try {
            $this->SysAdminDao->insert($data);

            if (! empty($param['mchIdList'])) {
                try {
                    $this->batchAddSysAdminMchRelation($data['id'],$param['mchIdList']);
                } catch (\Throwable $th) {
                    CustomUtils::xzxDebug($th);
                    throw new XZXValidationException("添加管理员商户关系表失败");
                }
                
            }
        } catch (\Throwable $th) {
            CustomUtils::xzxDebug($th);
            Db::rollBack();
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::ADD_FAIL));
        }
        Db::commit();
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function edit($param)
    {
        $info = $this->SysAdminDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        if($param['uid'] == $param['id'] && $param['status'] != 1)
        {
            throw new XZXValidationException("不能禁用自身状态");
        }

        $result = $this->SysRoleService->isSuperRole($info['roleId']);
        if(!$result['code'] && $param['status'] != 1)
        {
            throw new XZXValidationException("不能禁用超级管理员账号");
        }

        $id = $param['id'];
        $data = array();

        foreach($param as $k => $v){
            if(isset($v)){
                $data[$k] = $v;
            }
        }
        if(isset($data['password'])) {
            $salt = OpenService::getNonceStr(5);
            $newPassword = CustomUtils::genPassWord($data['password'], $salt);
            $data['password'] = $newPassword;
            $data['salt'] = $salt;
        }
        $mchIdList = $data['mchIdList'];
        unset($data['mchIdList']);
        unset($data['id']);
        unset($data['uid']);
        unset($data['password_confirmation']);
        unset($data['createBy']);
        
        CustomUtils::xzxDebug($data);
        
        Db::beginTransaction();
        try {
            $this->SysAdminDao->update($id, $data);

            $this->SysAdminMchRelationDao->delWhere(['adminId' => $param['id']]);

            // 如果关联商户
            if (! empty($mchIdList)) {
                try {
                    $this->batchAddSysAdminMchRelation($param['id'], $mchIdList);
                } catch (\Throwable $th) {
                    //throw $th;
                    throw new XZXValidationException("添加管理员商户关系表失败");
                }
                
            }
        } catch (\Throwable $th) {
            
            CustomUtils::xzxDebug($th);
            Db::rollBack();
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
        }
        Db::commit();
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function list(array $param)
    {

        $limit = $param['limit'];
        $page = $param['page'];        

        $total = $this->SysAdminDao->getCount($param);
        $list = $this->SysAdminDao->getList($param, $page, $limit);

//        CustomUtils::xzxDebug($list);

        $roleOptions = $this->SysRoleService->getOptions(null)['data'];
        $roleOptions = array_column($roleOptions, 'label', 'value');
        
        foreach ($list as $k => $v) {
//            CustomUtils::xzxDebug($v);
            
            unset($v['password']);            
            unset($v['salt']);   

            $v['strStatus']  = $this->SysAdminDao->strStatus($v['status']);
            $v['strRole']    = Arr::get($roleOptions, $v['roleId'], '-');            

            if(isset($v['createTime'])){
                $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            }
            $list[$k] = $v;
        }

        $data = array(
            'total' => $total,
            'list' => $list
        );

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }    

    private function batchAddSysAdminMchRelation($adminId,$mchIdList){
        // CustomUtils::xzxDebug($mchIdList);
        foreach ($mchIdList as $value) {
                    
            $admin_mch_relation_data = array(
                "id"         =>  CustomUtils::createUUID(),
                "adminId"    => $adminId,
                "mchId"      => $value,
                "createTime" => time(),
            );

            try {
                $this->SysAdminMchRelationDao->insert($admin_mch_relation_data);
            } catch (\Throwable $th) {
                CustomUtils::xzxDebug($th);
                throw new XZXValidationException("添加管理员商户关系表失败");
            } 
                        
        }
        return;
    }

    public function getStatusOptions () {
        $arr = $this->SysAdminDao->getStatusList();
        $options = ArrayUtils::ArrToOptions($arr);
        
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$options);
    }

    public function resetGoogleAuthSecret($param) {
        $info = $this->SysAdminDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        // 生成GoogleAuth密钥
        $googleAuthSecret = $this->CommonService->generateGoogleAuthSecret();
        // 更新用户
        $data = [
            'googleAuthSecret' => $googleAuthSecret
        ];
        try {
            $this->SysAdminDao->set($param['id'], $data);
        } catch (\Throwable $th) {
            //throw $th;
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
        }
        
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$googleAuthSecret);

    }

    public function login($param)
    {
        $member = $this->SysAdminDao->getWhere(['username' => $param['username']]);
        if(!$member)
        {
            //平台管理员不存在
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        if($member['status'] == 0)
        {
            // 管理员被禁用
            throw new XZXValidationException('管理员被禁用');
        }
        
        
        //密码验证
        $verifiedPassword = CustomUtils::genPassWord($param['password'], $member["salt"]);
        //密码不等
        if ($verifiedPassword !== $member["password"]) {
            throw new XZXValidationException('密码不一致');
        }

        if(!config("isDev")){
            // 验证码验证
            $verifyRet = $this->CommonService->checkGoogleCode($member['googleAuthSecret'], $param['code']);
            if ($verifyRet['code']) {
                throw new XZXValidationException($verifyRet['message']);
            }
        }
        CustomUtils::xzxDebug($member);
        $roleInfoResult = $this->SysRoleService->get(['id' => $member['roleId']]);
        if($roleInfoResult['code'])
        {
            //平台管理员对应的角色不存在
            throw new XZXValidationException('平台管理员对应的角色不存在');          
        }
        $roleInfo = $roleInfoResult['data'];
        
        if($roleInfo['status'] == 0)
        {
            //平台管理员对应的角色的状态不可用
            throw new XZXValidationException('平台管理员对应的角色的状态不可用');    
        }
        CustomUtils::xzxDebug($roleInfo);
        $member['isSuperRole'] = true;
        $result = $this->SysRoleService->isSuperRole($member['roleId']);
        CustomUtils::xzxDebug($result);
        if($result['code'])
        {
            $member['isSuperRole'] = false;
        }
        CustomUtils::xzxDebug($member);

        unset($member["salt"]);
        unset($member["password"]);
        unset($roleInfo['nodeIds']);

        $this->JWT->setScene("adminapi");
        $userData = array(    
            "uid"  => $member['id'],       
            "user" => $member,
            "role" => $roleInfo,
        );
        $token = $this->JWT->getToken($userData);
        
        // CustomUtils::xzxDebug($token);
        // $this->SysAdminDao->setLoginInfo($member['id'], $token);
        // CustomUtils::xzxDebug($this->SysAdminDao->getLoginInfo($member['id']));

        $data['token'] = $token;
        $data['username'] = $member['username'];
        $data['id'] = $member['id'];
        
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }

    public function getMchIdListByAdminId($userId)
    {
        $admin_mch_relation_data = $this->SysAdminMchRelationDao->getWhereList(['adminId' => $userId]);

        $mchIdArr = array();
        if(count($admin_mch_relation_data))
        {
            foreach ($admin_mch_relation_data as $v)
            {
                $mchIdArr[] = $v['mchId'];
            }
        }
        CustomUtils::xzxDebug($mchIdArr);
        return $mchIdArr;
    }

    //获取这个用户的后台菜单list
    public function menuList(string $userId)
    {
        //查找用户role
        $member_info  = $this->SysAdminDao->get($userId);
        CustomUtils::xzxDebug($member_info);
        //1,2,3,4,5,29,30,40,41,50,51,100,101,
        $node_data = $this->SysAccessDao->getWhereList(['roleId' => $member_info['roleId']]);
        
        $nodeIds = array_column($node_data,'nodeId');

        CustomUtils::xzxDebug($nodeIds);
        
        // $queryParam = array(
        //     'status' => 1
        // );
        $sortParam = array(
            'sort' => 'asc',
            'id'   => 'asc'
        );
        $node_data = $this->SysNodeDao->getWhereList(
            function (Builder $query) use ($nodeIds) {
                $query->where('status', 1);
                $query->whereIn('id', $nodeIds);
            },
            
            $sortParam
        );

        $parentIds = array_column($node_data, 'parentId');
        $parentIds = array_unique($parentIds);
        $uniqueParentIds = [];
        foreach ($parentIds as $value) {
            if (!in_array($value, $nodeIds)) {
                array_push($uniqueParentIds, $value);
            }
        }
        $parent_node_data = $this->SysNodeDao->getWhereList(
            function (Builder $query) use ($uniqueParentIds) {
                $query->where('status', 1);
                $query->whereIn('id', $uniqueParentIds);
            },
            
            $sortParam
        );

        $node_data = array_merge($node_data, $parent_node_data);

//        xeDebug($node_data);

        $tree = new Tree();
        $tree->init($node_data);
        $result = $tree->getTreeArray('root');

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$result);
    }  
    
    public function logout(array $param)
    {
        $member = $this->SysAdminDao->get($param['uid']);
        if (!$member) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        if(!$this->JWT->logout())
        {
            throw new XZXValidationException('logout 失败');
        }

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function getOption(array $param) {
        // 这里有数据权限，销售上级只能查看到所有下级用户；
        // 销售下级只能看到自己

        // 查询角色
        $user = $this->SysAdminDao->get($param['uid']);
        $role = $this->SysRoleDao->get($user['roleId']);

        if ($role['extraType'] == 1 && $user['level'] == 1) {
            // 是一级销售
            $param['parentId'] = $param['uid'];
        } else if ($role['extraType'] == 1 && $user['level'] == 2) {
            // 是二级销售
            $param['id'] = $param['uid'];
        }

        $result = $this->SysAdminDao->getOption($param);
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $result);
    }
}